#ifndef CODECOMPLETION_H
#define CODECOMPLETION_H

#include <M_Code_plugin.h>
#include <M_Code_project.h>
#include <sdk_events.h>
#include "coderefactoring.h"
#include "nativeparser.h"
#include "systemheadersthread.h"
#include "doxygen_parser.h"
#include <wx/arrstr.h>
#include <wx/listctrl.h>
#include <wx/string.h>
#include <wx/timer.h>
#include <map>
#include <vector>
#include <set>

class M_Code_Editor;
class wxScintillaEvent;
class wxChoice;
class DocumentationHelper;


class CodeCompletion : public cbCodeCompletionPlugin {
  public:
    struct FunctionScope {
      FunctionScope() {}
      FunctionScope( const NameSpace& ns ):
        StartLine( ns.StartLine ), EndLine( ns.EndLine ), Scope( ns.Name ) {}
      int StartLine;
      int EndLine;
      wxString ShortName;
      wxString Name;
      wxString Scope;
    };
    typedef std::vector<FunctionScope> FunctionsScopeVec;
    typedef std::vector<int> ScopeMarksVec;
    struct FunctionsScopePerFile {
      FunctionsScopeVec m_FunctionsScope;
      NameSpaceVec m_NameSpaces;
      bool parsed;
    };

    typedef std::map<wxString, FunctionsScopePerFile> FunctionsScopeMap;
    CodeCompletion();
    virtual ~CodeCompletion();
    virtual void OnAttach();
    virtual void OnRelease( bool appShutDown );
    virtual int GetConfigurationGroup() const { return cgEditor; }
    virtual cbConfigurationPanel* GetConfigurationPanel( wxWindow* parent );
    virtual cbConfigurationPanel* GetProjectConfigurationPanel( wxWindow* parent, M_Code_Project* project );
    virtual void BuildModuleMenu( const ModuleType type, wxMenu* menu, const FileTreeData* data = 0 );
    virtual bool BuildToolBar( wxToolBar* toolBar );
    virtual int GetToolBarPriority() { return 10; }
    virtual CCProviderStatus GetProviderStatusFor( M_Code_Editor* ed );
    virtual std::vector<CCToken> GetAutocompList( bool isAuto, M_Code_Editor* ed, int& tknStart, int& tknEnd );
    virtual std::vector<CCCallTip> GetCallTips( int pos, int style, M_Code_Editor* ed, int& argsPos );
    virtual wxString GetDocumentation( const CCToken& token );
    virtual std::vector<CCToken> GetTokenAt( int pos, M_Code_Editor* ed, bool& allowCallTip );
    virtual wxString OnDocumentationLink( wxHtmlLinkEvent& event, bool& dismissPopup );
    virtual void DoAutocomplete( const CCToken& token, M_Code_Editor* ed );
    wxArrayString GetLocalIncludeDirs( M_Code_Project* project, const wxArrayString& buildTargets );
    wxArrayString& GetSystemIncludeDirs( M_Code_Project* project, bool force );
    void GetAbsolutePath( const wxString& basePath, const wxArrayString& targets, wxArrayString& dirs );
    void EditorEventHook( M_Code_Editor* editor, wxScintillaEvent& event );
    void RereadOptions();
  private:
    void UpdateToolBar();
    void OnUpdateUI( wxUpdateUIEvent& event );
    void OnViewClassBrowser( wxCommandEvent& event );
    void OnGotoFunction( wxCommandEvent& event );
    void OnGotoPrevFunction( wxCommandEvent& event );
    void OnGotoNextFunction( wxCommandEvent& event );
    void OnClassMethod( wxCommandEvent& event );
    void OnUnimplementedClassMethods( wxCommandEvent& event );
    void OnGotoDeclaration( wxCommandEvent& event );
    void OnFindReferences( wxCommandEvent& event );
    void OnRenameSymbols( wxCommandEvent& event );
    void OnOpenIncludeFile( wxCommandEvent& event );
    void OnCurrentProjectReparse( wxCommandEvent& event );
    void OnSelectedProjectReparse( wxCommandEvent& event );
    void OnSelectedFileReparse( wxCommandEvent& event );
    void OnAppDoneStartup( CodeBlocksEvent& event );
    void OnWorkspaceChanged( CodeBlocksEvent& event );
    void OnProjectActivated( CodeBlocksEvent& event );
    void OnProjectClosed( CodeBlocksEvent& event );
    void OnProjectSaved( CodeBlocksEvent& event );
    void OnProjectFileAdded( CodeBlocksEvent& event );
    void OnProjectFileRemoved( CodeBlocksEvent& event );
    void OnProjectFileChanged( CodeBlocksEvent& event );
    void OnEditorSave( CodeBlocksEvent& event );
    void OnEditorOpen( CodeBlocksEvent& event );
    void OnEditorActivated( CodeBlocksEvent& event );
    void OnEditorClosed( CodeBlocksEvent& event );
    void OnCCLogger( CodeBlocksThreadEvent& event );
    void OnCCDebugLogger( CodeBlocksThreadEvent& event );
    void OnParserStart( wxCommandEvent& event );
    void OnParserEnd( wxCommandEvent& event );
    void OnSystemHeadersThreadUpdate( CodeBlocksThreadEvent& event );
    void OnSystemHeadersThreadFinish( CodeBlocksThreadEvent& event );
    void OnSystemHeadersThreadError( CodeBlocksThreadEvent& event );
    void DoCodeComplete( int caretPos, M_Code_Editor* ed, std::vector<CCToken>& tokens, bool preprocessorOnly = false );
    void DoCodeCompletePreprocessor( int tknStart, int tknEnd, M_Code_Editor* ed, std::vector<CCToken>& tokens );
    void DoCodeCompleteIncludes( M_Code_Editor* ed, int& tknStart, int tknEnd, std::vector<CCToken>& tokens );
    int DoClassMethodDeclImpl();
    int DoAllMethodsImpl();
    void MatchCodeStyle( wxString& str, int eolStyle = wxSCI_EOL_LF, const wxString& indent = wxEmptyString, bool useTabs = false, int tabSize = 4 );
    void FunctionPosition( int &scopeItem, int &functionItem ) const;
    void GotoFunctionPrevNext( bool next = false );
    int NameSpacePosition() const;
    void OnScope( wxCommandEvent& event );
    void OnFunction( wxCommandEvent& event );
    void ParseFunctionsAndFillToolbar();
    void FindFunctionAndUpdate( int currentLine );
    void UpdateFunctions( unsigned int scopeItem );
    void EnableToolbarTools( bool enable = true );
    void DoParseOpenedProjectAndActiveEditor();
    void UpdateEditorSyntax( M_Code_Editor* ed = NULL );
    void OnToolbarTimer( wxTimerEvent& event );
    void OnRealtimeParsingTimer( wxTimerEvent& event );
    void OnProjectSavedTimer( wxTimerEvent& event );
    void OnReparsingTimer( wxTimerEvent& event );
    void OnEditorActivatedTimer( wxTimerEvent& event );
    bool                    m_InitDone;
    wxMenu*                 m_EditMenu;
    wxMenu*                 m_SearchMenu;
    wxMenu*                 m_ViewMenu;
    wxMenu*                 m_ProjectMenu;
    NativeParser            m_NativeParser;
    CodeRefactoring         m_CodeRefactoring;
    int                     m_EditorHookId;
    wxTimer                 m_TimerRealtimeParsing;
    wxTimer                 m_TimerToolbar;
    wxTimer                 m_TimerProjectSaved;
    wxTimer                 m_TimerReparsing;
    wxTimer                 m_TimerEditorActivated;
    M_Code_Editor*               m_LastEditor;
    wxToolBar*              m_ToolBar;
    wxChoice*               m_Function;
    wxChoice*               m_Scope;
    FunctionsScopeVec       m_FunctionsScope;
    NameSpaceVec            m_NameSpaces;
    ScopeMarksVec           m_ScopeMarks;
    FunctionsScopeMap       m_AllFunctionsScopes;
    bool                    m_ToolbarNeedRefresh;
    bool                    m_ToolbarNeedReparse;
    int                     m_CurrentLine;
    wxString                m_LastFile;
    bool                    m_LexerKeywordsToInclude[9];
    bool                    m_NeedReparse;
    int                     m_CurrentLength;
    bool                    m_NeedsBatchColour;
    size_t                  m_CCMaxMatches;
    bool                    m_CCAutoAddParentheses;
    bool                    m_CCDetectImplementation;
    wxString                m_CCFillupChars;
    bool                    m_CCEnableHeaders;
    bool                    m_CCEnablePlatformCheck;
    SystemHeadersMap        m_SystemHeadersMap;
    std::list<SystemHeadersThread*> m_SystemHeadersThreads;
    wxCriticalSection               m_SystemHeadersThreadCS;
    typedef std::map<M_Code_Project*, wxArrayString> ReparsingMap;
    ReparsingMap m_ReparsingMap;
    DocumentationHelper     m_DocHelper;
    friend wxString DocumentationHelper::OnDocumentationLink( wxHtmlLinkEvent&, bool& );
    DECLARE_EVENT_TABLE()
};

#endif
